home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / libs / kpathsea / tex-file.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  13KB  |  345 lines

  1. /* tex-file.c: stuff for all TeX formats.
  2.  
  3. Copyright (C) 1993, 94, 95 Karl Berry.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  */
  18.  
  19. #include <kpathsea/config.h>
  20.  
  21. #include <kpathsea/c-vararg.h>
  22. #include <kpathsea/cnf.h>
  23. #include <kpathsea/default.h>
  24. #include <kpathsea/expand.h>
  25. #include <kpathsea/paths.h>
  26. #include <kpathsea/pathsearch.h>
  27. #include <kpathsea/tex-file.h>
  28.  
  29.  
  30. /* See tex-file.h.  */
  31. const_string kpse_fallback_font = NULL;
  32. unsigned *kpse_fallback_resolutions = NULL;
  33. string kpse_font_override_path = NULL;
  34. kpse_format_info_type kpse_format_info[kpse_last_format];
  35.  
  36. /* These are not in the structure
  37.    because it's annoying to initialize lists in C.  */
  38. #define KPSE_GF_ENVS "GFFONTS", KPSE_GLYPH_ENVS
  39. #define KPSE_PK_ENVS "PKFONTS", "TEXPKS", KPSE_GLYPH_ENVS
  40. #define KPSE_GLYPH_ENVS "GLYPHFONTS", "TEXFONTS"
  41. #define KPSE_BASE_ENVS "MFBASES"
  42. #define KPSE_BIB_ENVS "BIBINPUTS"
  43. #define KPSE_BST_ENVS "BSTINPUTS"
  44. #define KPSE_CNF_ENVS "TEXMFCNF"
  45. #define KPSE_FMT_ENVS "TEXFORMATS"
  46. #define KPSE_MF_ENVS "MFINPUTS"
  47. #define KPSE_MFPOOL_ENVS "MFPOOL"
  48. #define KPSE_PICT_ENVS "TEXPICTS", KPSE_TEX_ENVS
  49. #define KPSE_TEX_ENVS "TEXINPUTS"
  50. #define KPSE_TEXPOOL_ENVS "TEXPOOL"
  51. #define KPSE_TFM_ENVS "TFMFONTS", "TEXFONTS"
  52. #define KPSE_VF_ENVS "VFFONTS", "TEXFONTS"
  53. #define KPSE_DVIPS_CONFIG_ENVS "TEXCONFIG"
  54. #define KPSE_DVIPS_HEADER_ENVS "DVIPSHEADERS"
  55.  
  56. /* The compiled-in default list, DEFAULT_FONT_SIZES, is intended to be
  57.    set from the command line (presumably via the Makefile).  */
  58.  
  59. #ifndef DEFAULT_FONT_SIZES
  60. #define DEFAULT_FONT_SIZES ""
  61. #endif
  62.  
  63. void
  64. kpse_init_fallback_resolutions P1C(string, envvar)
  65. {
  66.   const_string size_var = ENVVAR (envvar, "TEXSIZES");
  67.   string size_str = getenv (size_var);
  68.   unsigned *last_resort_sizes = NULL;
  69.   unsigned size_count = 0;
  70.   string size_list = kpse_expand_default (size_str, DEFAULT_FONT_SIZES);
  71.  
  72.   /* Initialize the list of last-resort sizes.  */
  73.   for (size_str = kpse_path_element (size_list); size_str != NULL;
  74.        size_str = kpse_path_element (NULL))
  75.     {
  76.       if (! *size_str)
  77.         continue;
  78.  
  79.       size_count++;
  80.       XRETALLOC (last_resort_sizes, size_count, unsigned);
  81.       last_resort_sizes[size_count - 1] = atoi (size_str);
  82.     }
  83.  
  84.   /* Add a zero to mark the end of the list.  */
  85.   size_count++;
  86.   XRETALLOC (last_resort_sizes, size_count, unsigned);
  87.   last_resort_sizes[size_count - 1] = 0;
  88.  
  89.   kpse_fallback_resolutions = last_resort_sizes;
  90. }
  91.  
  92. /* Find the final search path to use for the format entry INFO, given
  93.    FONT_P (whether the font override path applies), the compile-time
  94.    default (DEFAULT_PATH), and the environment variables to check (the
  95.    remaining arguments, terminated with NULL).  We set the `path' and
  96.    `path_source' members of INFO.  The `client_path' member must already
  97.    be set upon entry.  */
  98.    
  99. #define EXPAND_DEFAULT(try_path, source_string)            \
  100. if (try_path)                            \
  101.   {                                \
  102.     info->raw_path = try_path;                    \
  103.     info->path = kpse_expand_default (try_path, info->path);    \
  104.     info->path_source = source_string;                \
  105.   }
  106.  
  107. static void
  108. init_path PVAR3C(kpse_format_info_type *, info,  boolean, font_p,
  109.                  const_string, default_path,  ap)
  110. {
  111.   string env_name;
  112.   string var = NULL;
  113.   
  114.   info->font_override_p = font_p;
  115.   info->default_path = default_path;
  116.  
  117.   /* First envvar that's set to a nonempty value will exit the loop.  If
  118.      none are set, we want the first cnf entry that matches.  Find the
  119.      cnf entries simultaneously, to avoid having to go through envvar
  120.      list twice -- because of the PVAR?C macro, that would mean having
  121.      to create a str_list and then use it twice.  Yuck.  */
  122.   while ((env_name = va_arg (ap, string)) != NULL)
  123.     {
  124.       if (!var)
  125.         {
  126.           string env_value = getenv (env_name);
  127.           if (env_value && *env_value)
  128.             var = env_name;
  129.         }
  130.  
  131.       /* If we are initializing the cnf path, don't try to get any
  132.          values from the cnf files; that's infinite loop time.  */
  133.       if (!info->cnf_path && (!info->suffix || !STREQ (info->suffix, ".cnf")))
  134.         info->cnf_path = kpse_cnf_get (env_name);
  135.       
  136.       if (var && info->cnf_path)
  137.         break;
  138.     }
  139.   va_end (ap);
  140.   
  141.   /* Expand any extra :'s.  For each level (the font override path down
  142.      through the compile-time default), an extra : should be replaced
  143.      with the path at the next lower level.  For example, an extra : in
  144.      a user-set envvar should be replaced with the path from the cnf
  145.      file.  Things are complicated because none of the levels above the
  146.      very bottom are guaranteed to exist.  */
  147.  
  148.   /* Assume we can reliably start with the compile-time default.  */
  149.   info->path = info->raw_path = info->default_path;
  150.   info->path_source = "compile-time paths.h";
  151.  
  152.   EXPAND_DEFAULT (info->cnf_path, "texmf.cnf");
  153.   EXPAND_DEFAULT (info->client_path, "program config file");
  154.   if (var)
  155.     EXPAND_DEFAULT (getenv (var), concat (var, " environment variable"));
  156.   if (info->font_override_p)
  157.     EXPAND_DEFAULT (kpse_font_override_path, "font override variable");
  158.   info->path = kpse_path_expand (info->path);
  159. }}
  160.  
  161.  
  162. /* The path spec we are defining, one element of the global array.  */
  163. #define FMT_INFO kpse_format_info[format]
  164.  
  165. /* Call `init_path', including appending the trailing NULL to the envvar
  166.    list. Also initialize the fields not needed in setting the path.
  167.    Don't set `program_enabled' -- it'll be false via the compiler
  168.    initialization, and programs may want to enable it beforehand.  */
  169. #define INIT_FORMAT(ext, font_p, default_path, envs) \
  170.   FMT_INFO.suffix = FMT_INFO.type = ext; \
  171.   init_path (&FMT_INFO, font_p, default_path, envs, NULL)
  172.  
  173. /* A few file types allow for runtime generation by an external program.  */
  174. #define INIT_MT(prog, args) \
  175.   FMT_INFO.program = prog; FMT_INFO.program_args = args
  176. #define MAKETEXPK_SPEC \
  177.   "$KPATHSEA_DPI $MAKETEX_BASE_DPI $MAKETEX_MAG $MAKETEX_MODE"
  178.  
  179. /* Initialize everything for FORMAT.  */
  180.  
  181. const_string
  182. kpse_init_format P1C(kpse_file_format_type, format)
  183. {
  184.   /* If we get called twice, don't redo all the work.  */
  185.   if (FMT_INFO.path)
  186.     return FMT_INFO.path;
  187.     
  188.   switch (format)
  189.     { /* We could avoid this repetition by token pasting, but it doesn't
  190.          seem worth it.  */
  191.     case kpse_gf_format:
  192.       INIT_FORMAT ("gf", true, DEFAULT_GFFONTS, KPSE_GF_ENVS);
  193.       FMT_INFO.suffix_search_only = false;
  194.       break;
  195.     case kpse_pk_format:
  196.       INIT_MT ("MakeTeXPK", MAKETEXPK_SPEC);
  197.       INIT_FORMAT ("pk", true, DEFAULT_PKFONTS, KPSE_PK_ENVS);
  198.       FMT_INFO.suffix_search_only = true;
  199.       break;
  200.     case kpse_any_glyph_format:
  201.       INIT_MT ("MakeTeXPK", MAKETEXPK_SPEC);
  202.       INIT_FORMAT ("bitmap", true, DEFAULT_GLYPHFONTS, KPSE_GLYPH_ENVS);
  203.       FMT_INFO.suffix_search_only = true;
  204.       break;
  205.     case kpse_base_format:
  206.       INIT_FORMAT (".base", false, DEFAULT_MFBASES, KPSE_BASE_ENVS);
  207.       break;
  208.     case kpse_bib_format:
  209.       INIT_FORMAT (".bib", false, DEFAULT_BIBINPUTS, KPSE_BIB_ENVS);
  210.       break;
  211.     case kpse_bst_format:
  212.       INIT_FORMAT (".bst", false, DEFAULT_BSTINPUTS, KPSE_BST_ENVS);
  213.       break;
  214.     case kpse_cnf_format:
  215.       /* I admit this is ugly, but making another field just for
  216.          this one file type seemed a waste.  We use this value in cnf.c
  217.          as the filename to search for in the path.  */
  218.       if (!FMT_INFO.program)
  219.         FMT_INFO.program = "texmf.cnf";
  220.       INIT_FORMAT (".cnf", false, DEFAULT_TEXMFCNF, KPSE_CNF_ENVS);
  221.       break;
  222.     case kpse_fmt_format:
  223.       INIT_FORMAT (".fmt", false, DEFAULT_TEXFORMATS, KPSE_FMT_ENVS);
  224.       break;
  225.     case kpse_mf_format:
  226.       INIT_MT ("MakeTeXMF", NULL);
  227.       INIT_FORMAT (".mf", false, DEFAULT_MFINPUTS, KPSE_MF_ENVS);
  228.       break;
  229.     case kpse_mfpool_format:
  230.       INIT_FORMAT (".pool", false, DEFAULT_MFPOOL, KPSE_MFPOOL_ENVS);
  231.       break;
  232.     case kpse_tex_format:
  233.       INIT_MT ("MakeTeXTeX", NULL);
  234.       INIT_FORMAT (".tex", false, DEFAULT_TEXINPUTS, KPSE_TEX_ENVS);
  235.       break;
  236.     case kpse_texpool_format:
  237.       INIT_FORMAT (".pool", false, DEFAULT_TEXPOOL, KPSE_TEXPOOL_ENVS);
  238.       break;
  239.     case kpse_pict_format:
  240.       INIT_FORMAT (NULL, false, DEFAULT_TEXINPUTS, KPSE_PICT_ENVS);
  241.       FMT_INFO.type = "graphic/figure";
  242.       break;
  243.     case kpse_tfm_format:
  244.       INIT_MT ("MakeTeXTFM", NULL);
  245.       INIT_FORMAT (".tfm", false, DEFAULT_TFMFONTS, KPSE_TFM_ENVS);
  246.       FMT_INFO.suffix_search_only = true;
  247.       break;
  248.     case kpse_vf_format:
  249.       INIT_FORMAT (".vf", false, DEFAULT_VFFONTS, KPSE_VF_ENVS);
  250.       FMT_INFO.suffix_search_only = true;
  251.       break;
  252.     case kpse_dvips_config_format:
  253.       INIT_FORMAT (NULL, false, DEFAULT_TEXCONFIG, KPSE_DVIPS_CONFIG_ENVS);
  254.       FMT_INFO.type = "dvips config";
  255.       break;
  256.     case kpse_dvips_header_format:
  257.       INIT_FORMAT (NULL, false, DEFAULT_DVIPSHEADERS, KPSE_DVIPS_HEADER_ENVS);
  258.       FMT_INFO.type = "dvips header/type1 font";
  259.       break;
  260.     default:
  261.       FATAL1 ("(kpathsea) init_path: Unknown format %d", format);
  262.     }
  263.  
  264. #ifdef DEBUG
  265. #define MAYBE_NULL(member) (FMT_INFO.member ? FMT_INFO.member : "(none)")
  266.  
  267.   /* Describe the monster we've created.  */
  268.   if (KPSE_DEBUG_P (KPSE_DEBUG_PATHS))
  269.     {
  270.       DEBUGF2 ("Search path for %s files (from %s)\n",
  271.               FMT_INFO.type, FMT_INFO.path_source);
  272.       DEBUGF1 ("  = %s\n", FMT_INFO.path);
  273.       DEBUGF1 ("  before expansion = %s\n", FMT_INFO.raw_path);
  274.       DEBUGF1 ("  font override var applies = %d\n", FMT_INFO.font_override_p);
  275.       DEBUGF1 ("  application config file path = %s\n",
  276.               MAYBE_NULL (client_path));
  277.       DEBUGF1 ("  texmf.cnf path = %s\n", MAYBE_NULL (cnf_path));
  278.       DEBUGF1 ("  compile-time path = %s\n", MAYBE_NULL (default_path));
  279.       DEBUGF1 ("  suffix = %s\n", MAYBE_NULL (suffix));
  280.       DEBUGF1 ("  search only with suffix = %d\n",
  281.                FMT_INFO.suffix_search_only);
  282.       DEBUGF1 ("  runtime generation program = %s\n", MAYBE_NULL (program));
  283.       DEBUGF1 ("  extra program args = %s\n", MAYBE_NULL (program_args));
  284.       /* Don't print the `program_enabled_p' member, since it's likely
  285.          always false (made true on a per-font basis), and hence it
  286.          would just confuse matters.  */
  287.     }
  288. #endif /* DEBUG */
  289.  
  290.   return FMT_INFO.path;
  291. }
  292.  
  293. /* Look up a file NAME of type FORMAT, and the given MUST_EXIST.  This
  294.    initializes the path spec for FORMAT if it's the first lookup of that
  295.    type.  Return the filename found, or NULL.  */
  296.    
  297. string
  298. kpse_find_file P3C(const_string, name,  kpse_file_format_type, format,
  299.                    boolean, must_exist)
  300. {
  301.   boolean name_has_suffix;
  302.   const_string suffix;
  303.   string ret = NULL;
  304.  
  305.   if (FMT_INFO.path == NULL)
  306.     kpse_init_format (format);
  307.  
  308.   suffix = FMT_INFO.suffix;
  309.   
  310.   /* Does NAME already end in `.suffix'?  */
  311.   if (suffix)
  312.     { /* Don't do the strlen's at all if no SUFFIX.  */
  313.       unsigned suffix_len = strlen (suffix);
  314.       unsigned name_len = strlen (name);
  315.       name_has_suffix = (name_len > suffix_len
  316.                          && STREQ (suffix, name + name_len - suffix_len));
  317.     }
  318.   else
  319.     name_has_suffix = false;
  320.   
  321.   if (suffix && !name_has_suffix)
  322.     {
  323.       /* Append `.suffix' and search for it.  If we're going to search
  324.          for the original name if this fails, then set must_exist=false;
  325.          otherwise, we'd be looking on the disk for foo.eps.tex.  */
  326.       string full_name = concat (name, suffix);
  327.       ret = kpse_path_search (FMT_INFO.path, full_name,
  328.                              FMT_INFO.suffix_search_only ? must_exist : false);
  329.       free (full_name);
  330.     }
  331.  
  332.   /* For example, looking for foo.eps, first we look for foo.eps.tex,
  333.      which presumably fails, then we want to look for foo.eps.  (But we
  334.      want to find foo.tex before foo, so have to try with `suffix'
  335.      first.)  Another example: tftopl passes in cmr10.tfm, but the
  336.      drivers just pass in cmr10. To avoid pounding the disk for `cmr10',
  337.      `suffix_search_only' for PK format is true. But then
  338.      `name_has_suffix' must override, or tftopl would wind up doing
  339.      no searches at all.  */
  340.   if (!ret && (name_has_suffix || !FMT_INFO.suffix_search_only))
  341.     ret = kpse_path_search (FMT_INFO.path, name, must_exist);
  342.  
  343.   return ret;
  344. }
  345.